#include "linked_stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STACK_SUCCESS 1
#define STACK_FAILURE 0

int stack_init(Stack **st, size_t size) {
  if (st == NULL)
    return STACK_FAILURE; // 增加输入检查

  *st = malloc(sizeof(Stack));
  if (*st == NULL) {
    return STACK_FAILURE;
  }
  (*st)->top = NULL;
  (*st)->nmemb = 0;
  (*st)->size = size;
  return STACK_SUCCESS;
}

int stack_empty(const Stack *st) {
  return (st == NULL) || (st->nmemb == 0); // 增加空指针检查
}

size_t stack_nmemb(const Stack *st) {
  return (st == NULL) ? 0 : st->nmemb; // 增加空指针检查
}

void stack_pop(Stack *st) {
  if (st == NULL) { // 增加栈指针为空检查
    fprintf(stderr, "ERROR: POP A NULL STACK\n");
    return;
  }
  if (stack_empty(st)) {
    fprintf(stderr, "ERROR: POP A EMPTY STACK\n");
    return;
  }
  node *del_node = st->top;
  st->top = st->top->next;
  free(del_node->data);
  free(del_node);
  // del_node = NULL;  // 这行可以去掉，因为del_node是局部变量
  st->nmemb--;
}

void *stack_top(const Stack *st) {
  if (st == NULL) { // 增加栈指针为空检查
    fprintf(stderr, "ERROR: TOP A NULL STACK\n");
    return NULL;
  }
  if (stack_empty(st)) {
    fprintf(stderr, "ERROR: TOP A EMPTY STACK\n");
    return NULL;
  }
  return st->top->data;
}

int stack_push(Stack *st, const void *data) {
  if (st == NULL || data == NULL) { // 增加输入检查
    fprintf(stderr, "ERROR: PUSH TO NULL STACK OR WITH NULL DATA\n");
    return STACK_FAILURE;
  }

  node *new_node = malloc(sizeof(node));
  if (new_node == NULL) {
    return STACK_FAILURE;
  }
  new_node->data = malloc(st->size);
  if (new_node->data == NULL) {
    free(new_node);
    return STACK_FAILURE;
  }
  memcpy(new_node->data, data, st->size);
  new_node->next = st->top;
  st->top = new_node;
  st->nmemb++;
  return STACK_SUCCESS;
}

void stack_destroy(Stack **st) {
  if (st == NULL || *st == NULL) {
    return;
  }

  while (!stack_empty(*st)) {
    stack_pop(*st);
  }
  free(*st);
  *st = NULL;
}
